/**
@description base文件

@copyright    Copyright 2021 高灯科技
@version      1.0.0
@link         https://www.goldentec.com
@author       venki.chen <venki.chen@goldentec.com>
@datetime     2021/11/17 9:39
*/

package base

import (
	"fmt"
	"reflect"
)

type Animal interface {
	Sleep()
	GetColor() string
	GetType() string
}

type Cat struct {
	Color string
	Name  string
}

type Dog struct {
	Color string
	Name  string
}

func init() {
	fmt.Println("base模块初始化成功……")
}

func AccessBase() {
	// 多态练习
	/*cat := Cat{
		Color: "Green",
		Name:  "小猫咪",
	}

	PolymorphicLearn(&cat)
	fmt.Println("------------------")

	dog := Dog{
		Color: "white",
		Name:  "小迪迪",
	}
	PolymorphicLearn(&dog)*/

	// 空接口
	/*InterfaceLearn(10)
	InterfaceLearn(10.00)
	InterfaceLearn("10")
	InterfaceLearn(Cat{
		Color: "",
		Name:  "",
	})*/
	// 反射 - 简单数据类型
	/*var r1 float64 = 10.69
	ReflectLearn(r1)*/

	// 反射 - 复杂数据类型
	cat := Cat{
		Color: "Green",
		Name:  "小猫咪",
	}
	ReflectLearn(cat)
}

func ReflectLearn(arg interface{}) {
	// 简单数据类型的反射练习
	/*fmt.Printf("arg's type is %v\n", reflect.TypeOf(arg))
	fmt.Printf("arg's value is %v\n", reflect.ValueOf(arg))*/

	// 复杂数据类型的反射练习

	// 获取arg的type
	argType := reflect.TypeOf(arg)
	fmt.Println("argType is :", argType.Name())

	// 获取arg的value
	argValue := reflect.ValueOf(arg)
	fmt.Println("argValue is :", argValue)

	// 通过argType获取里面的字段
	// 通过argValue获取里面字段值
	// 1. 获取interface的reflect.Type,通过type得到NumField，进行遍历
	// 2. 得到field，数据类型
	// 3. 通过field的Interface{}方法得到对应字段值
	for i := 0; i < argType.NumField(); i++ {
		field := argType.Field(i)
		value := argValue.Field(i).Interface()

		fmt.Printf("%s:%v = %v\n", field.Name, field.Type, value)
	}

	// 通过type获取里面的方法
	for i := 0; i < argType.NumMethod(); i++ {
		m := argType.Method(i)
		fmt.Printf("%s:%v\n", m.Name, m.Type)
	}
}

func InterfaceLearn(args interface{}) {
	fmt.Println("interfaceLearn is called...")
	// 类型断言
	value, ok := args.(string)
	if !ok {
		fmt.Println("args is not string type")

		fmt.Println("args is string type,value=", args)
	} else {
		fmt.Println("args is string type,value=", value)

		fmt.Printf("value type is %T\n", value)
	}
	fmt.Println("-----------------------------")
}

func PolymorphicLearn(animal Animal) {
	animal.Sleep()
	animal.GetColor()
	animal.GetType()
}

func (this *Cat) Call() {
	fmt.Println("cat's is call...")
}

func (this *Cat) Sleep() {
	fmt.Println("cat is sleeping...")
}

func (this *Cat) GetColor() string {
	fmt.Println("cat's color is", this.Color)
	return this.Color
}

func (this *Cat) GetType() string {
	fmt.Println("cat's type is", this.Name)
	return this.Name
}

func (this *Dog) Sleep() {
	fmt.Println("dog is sleeping...")
}

func (this *Dog) GetColor() string {
	fmt.Println("dog's color is", this.Color)
	return this.Color
}

func (this *Dog) GetType() string {
	fmt.Println("dog's type is", this.Name)
	return this.Name
}
